using System.Collections.Generic;
using Gameplay.PVE.Entity;
using UnityEngine;
using Yoozoo.Libs;

namespace Gameplay.PVE
{
    public abstract class UnitRoadPath : IClass
    {
        protected UnitBase unit;
        public bool isFinish;
        public Vector3 position;
        public string actionName = "Walk";
        public float actionSpeed = 1;
        
        //a星寻路相关
        public bool needRepath = false;
        protected List<Vector3> pathList = new List<Vector3>();
        protected float lastRepathTime;
        protected float lastFindPathFailTime;
        private int nextIndex = 0;
        protected bool isFindPathSuccess = false;
        public bool needShowPath = false;
        private uint lineId;
        protected Vector3 targetPosition;


        
        void IClass.OnReset()
        {
            Reset();
        }

        protected virtual void Reset()
        {
            HidePath();
        }
        
        public virtual void Init(UnitBase unit)
        {
            this.unit = unit;
            position = unit.Data.position;
        }
        

        public virtual void Update()
        {
            
        }

        public virtual void UpdateData()
        {
            
        }

        public virtual void DoSpecialCase(UnitOrder order)
        {
            
        }

        public virtual void OnTransmit(ETransmitType type,BaseTransmitArg arg)
        {
            
        }

        public virtual void OnDead()
        {
            
        }
        
        protected void ShowPath()
        {
            HidePath();
            var points = pathList;
            List<Vector2> pointList = new List<Vector2>();
            for (int i = 0; i < points.Count; i++)
            {
                var point = points[i];
                pointList.Add(new Vector2
                {
                    x = point.x,
                    y = point.z
                });
            }

            LineInfo line = new LineInfo()
            {
                color = Color.green,
                speed = 1,
                isPart = true,
                isHeadPart = true,
            };
            lineId = (uint)DrawLineTool.GetInstance().AddMultiLines(line, pointList);
        }

        protected void HidePath()
        {
            if (lineId != 0)
            {
                DrawLineTool.GetInstance().DelMultiLines(lineId);
                lineId = 0;
            }
        }
        
        //移动到目标点
        protected bool MoveToTargetPosition(Vector3 targetPosition,float moveSpeedRatio = 1,bool forward = true)
        {
            Vector3 diff = targetPosition - unit.Data.position;
            if (diff != Vector3.zero && forward)
            {
                unit.Data.SetTargetForward(diff);
            }
            
            float distance = diff.magnitude;
            float normalizedSpeedValue = unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime * moveSpeedRatio;
            if (normalizedSpeedValue < distance)
            {
                Vector3 normalizedSpeed = normalizedSpeedValue * diff.normalized;
                position = unit.Data.position + normalizedSpeed;
                return false;
            }
            else
            {
                position = targetPosition;
                return true;
            }
        }

        //返回剩余的步长
        private bool MoveToPathPoint(Vector3 startPosition,Vector3 targetPosition,ref float speed, bool forward = true)
        {
            Vector3 diff = targetPosition - startPosition;
            if (diff != Vector3.zero && forward)
            {
                if (unit.Data.moveType == 0)
                {
                    unit.Data.SetTargetForward(diff);
                }
                else if (unit.Data.moveType == 2)
                {
                    unit.Data.SetTargetForward(this.targetPosition - unit.Data.position);
                }
            }
            
            float distance = diff.magnitude;
            if (speed < distance)
            {
                Vector3 normalizedSpeed = speed * diff.normalized;
                position = startPosition + normalizedSpeed;
                speed = 0;
                return false;
            }
            else
            {
                position = targetPosition;
                speed = speed - distance;
                return true;
            }
        }
        
        //计算a星寻路
        public void UpdateAStarPath(Vector3 start,Vector3 end,bool isForceToEnd = false)
        {
            isFindPathSuccess = PveFindPathManager.Instance.GetPathByObstacle(ref pathList,unit.Data.id,start, end,isForceToEnd);
            if (!isFindPathSuccess)
            {
                lastFindPathFailTime = TimeManager.logicTime;
                lastRepathTime = 0;
            }
            else
            {
                lastFindPathFailTime = 0;
                lastRepathTime = TimeManager.logicTime;
            }
            if (PveGlobalVlues.ShowAstarPath)
            {
                ShowPath();
            }
            nextIndex = 0;
            ToNextPoint();
        }
        
        protected void UpdateRoadPath(bool forward = true)
        {
            if (pathList.Count > nextIndex )
            {
                if (nextIndex > 0)
                {
                    Vector3 targetPosition = pathList[nextIndex];
                    position = unit.Data.position;
                    float speed = unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime;
                    bool reach = MoveToPathPoint(position, targetPosition, ref speed, forward);
                    while (speed > 0)
                    {
                        ToNextPoint();
                        if (pathList.Count <= nextIndex || pathList.Count == 0)
                        {
                            break;
                        }
                        targetPosition = pathList[nextIndex];
                        reach = MoveToPathPoint(position, targetPosition, ref speed, forward);
                    }
                }
                else
                {
                    ToNextPoint();
                }
            }
        }
        
        
        
        private void ToNextPoint()
        {
            position = pathList[nextIndex];
            if (nextIndex < pathList.Count - 1)
            {
                nextIndex++;
            }
            else
            {
                pathList.Clear();
                unit.Data.position = position;
            }
        }
    }
}